package cn.ug.pay.service.impl;

import cn.ug.aop.RemoveCache;
import cn.ug.aop.SaveCache;
import cn.ug.bean.base.DataOtherTable;
import cn.ug.bean.base.DataTable;
import cn.ug.bean.base.SerializeObject;
import cn.ug.bean.status.DeleteStatus;
import cn.ug.config.FundRateConfig;
import cn.ug.config.RedisGlobalLock;
import cn.ug.core.ensure.Ensure;
import cn.ug.enums.RateKeyEnum;
import cn.ug.enums.WxTemplateEnum;
import cn.ug.feign.RateSettingsService;
import cn.ug.msg.bean.status.CommonConstants;
import cn.ug.msg.mq.Msg;
import cn.ug.msg.mq.WxMessageParamBean;
import cn.ug.msg.mq.WxNotifyData;
import cn.ug.pay.bean.WithdrawAuditBean;
import cn.ug.pay.bean.WithdrawBean;
import cn.ug.pay.bean.response.WithdrawSettingBean;
import cn.ug.pay.bean.status.TradeStatus;
import cn.ug.pay.bean.status.WithdrawAuditStatus;
import cn.ug.pay.bean.type.BillType;
import cn.ug.pay.bean.type.TradeType;
import cn.ug.pay.mapper.BillMapper;
import cn.ug.pay.mapper.MemberAccountMapper;
import cn.ug.pay.mapper.WithdrawMapper;
import cn.ug.pay.mapper.WithdrawSettingMapper;
import cn.ug.pay.mapper.entity.Bill;
import cn.ug.pay.mapper.entity.MemberAccount;
import cn.ug.pay.mapper.entity.Withdraw;
import cn.ug.pay.mapper.entity.WithdrawDetail;
import cn.ug.pay.mq.WithdrawMQ;
import cn.ug.pay.service.MemberAccountService;
import cn.ug.pay.service.TradeService;
import cn.ug.pay.service.WithdrawService;
import cn.ug.service.impl.BaseServiceImpl;
import cn.ug.util.BigDecimalUtil;
import cn.ug.util.SerialNumberWorker;
import cn.ug.util.UF;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.apache.commons.lang3.StringUtils;
import org.dozer.DozerBeanMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;
import java.util.*;

import static cn.ug.config.CacheType.OBJECT;
import static cn.ug.config.CacheType.SEARCH;
import static cn.ug.config.QueueName.*;

/**
 * @author kaiwotech
 */
@Service
public class WithdrawServiceImpl extends BaseServiceImpl implements WithdrawService {
    @Autowired
    private BillMapper billMapper;
    @Resource
    private WithdrawMapper withdrawMapper;

    @Resource
    private MemberAccountService memberAccountService;

    @Resource
    private TradeService tradeService;

    @Resource
    private DozerBeanMapper dozerBeanMapper;

    @Resource
    private WithdrawSettingMapper withdrawSettingMapper;

    @Resource
    private RedisGlobalLock redisGlobalLock;

    @Resource
    private FundRateConfig fundRateConfig;
    @Resource
    private RateSettingsService rateSettingsService;
    @Resource
    private AmqpTemplate amqpTemplate;
    @Autowired
    private MemberAccountMapper memberAccountMapper;
    private static Logger logger = LoggerFactory.getLogger(WithdrawServiceImpl.class);

    @Override
    @RemoveCache(cleanSearch = true)
    @Transactional(rollbackFor = Exception.class)
    public int save(WithdrawBean entityBean) {
        // 数据完整性校验
        if (null == entityBean || StringUtils.isBlank(entityBean.getMemberId()) ||
                StringUtils.isBlank(entityBean.getBankCardId()) || BigDecimalUtil.isZeroOrNull(entityBean.getAmount())
                || entityBean.getAmount().compareTo(BigDecimal.valueOf(2)) < 0) {
            Ensure.that(true).isTrue("00000002");
        }


        String key = "WithdrawServiceImpl:save:" + entityBean.getMemberId();
        if (!redisGlobalLock.lock(key)) {
            Ensure.that(true).isTrue("17000714");
        }

        //校验限额
        WithdrawSettingBean settingBean = withdrawSettingMapper.findByBankCode(entityBean.getBankCode());
        Ensure.that(settingBean == null).isTrue("17001001");
        Map<String, Object> settingMap = new HashMap<String, Object>();
        settingMap.put("memberId", entityBean.getMemberId());

        //验证单笔限额
        if (TradeStatus.Flag.NO == settingBean.getOnceType()) {
            Ensure.that(entityBean.getAmount().compareTo(settingBean.getAmountOnce()) > 0).isTrue("17001002");
        }
        //验证每日限额
        if (TradeStatus.Flag.NO == settingBean.getDayType()) {
            settingMap.put("startTime", LocalDate.now().toString()); //当日
            BigDecimal total = withdrawMapper.findWithdrawTotal(settingMap);
            BigDecimal amount = entityBean.getAmount().add(total);
            logger.info("------日-----" + amount + "----day---" + settingBean.getAmountDay());
            Ensure.that(amount.compareTo(settingBean.getAmountDay()) > 0).isTrue("17001003");
        }
        //验证每月限额
        if (TradeStatus.Flag.NO == settingBean.getMonthType()) {
            LocalDate firstDay = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth()); // 2018-05-01
            settingMap.put("startTime", firstDay);
            BigDecimal total = withdrawMapper.findWithdrawTotal(settingMap);
            BigDecimal amount = entityBean.getAmount().add(total);
            logger.info("------月-----" + amount + "----month----" + settingBean.getAmountMonth());
            Ensure.that(amount.compareTo(settingBean.getAmountMonth()) > 0).isTrue("17001004");
        }

        try {
            MemberAccount memberAccount = memberAccountMapper.findByMemberId(entityBean.getMemberId());
            if (memberAccount == null) {
                Ensure.that(true).isTrue("00000002");
            }
            // 冻结资金（可能会抛出余额不足异常）
            memberAccountService.withdraw(entityBean.getMemberId(), entityBean.getAmount());

            Withdraw entity = dozerBeanMapper.map(entityBean, Withdraw.class);
            if (StringUtils.isBlank(entity.getId())) {
                entity.setId(UF.getRandomUUID());
            }
            if (StringUtils.isBlank(entity.getOrderId())) {
                entity.setOrderId(SerialNumberWorker.getInstance().nextId());
            }
            SerializeObject rateBean = rateSettingsService.get(RateKeyEnum.WITHDRAW.getKey());
            BigDecimal fee = BigDecimal.ZERO;
            if (rateBean != null && rateBean.getData() != null) {
                JSONObject json = JSON.parseObject(JSONObject.toJSONString(rateBean.getData()));
                BigDecimal minAmount = json.getBigDecimal("minAmount");
                if (minAmount != null && entity.getAmount().compareTo(minAmount) < 0) {
                    Ensure.that(0).isLt(1, "17002041");
                }
                int dayNum = withdrawMapper.getWithdrawNumForThisDay(entityBean.getMemberId());
                int monthNum = withdrawMapper.getWithdrawNumForThisMonth(entityBean.getMemberId());
                fee = fundRateConfig.getFee(json, entity.getAmount(), dayNum, monthNum);
            }
            entity.setFee(fee);
            entity.setActualAmount(BigDecimalUtil.to2Point(BigDecimalUtil.subtract(entity.getAmount(), fee)));
            entity.setBalance(memberAccount.getUsableAmount());
            int rows = withdrawMapper.insert(entity);
            Ensure.that(rows).isLt(1, "17000102");

            Bill billBean = new Bill();
            billBean.setOrderId(entity.getOrderId());
            billBean.setId(UF.getRandomUUID());
            billBean.setMemberId(entity.getMemberId());
            billBean.setAmount(entity.getAmount());
            billBean.setActualAmount(entity.getActualAmount());
            billBean.setFee(entity.getFee());
            billBean.setType(BillType.OUTLAY.getValue());
            billBean.setTradeType(TradeType.HANDLING_WITHDRAW.getValue());
            rows = billMapper.insert(billBean);
            Ensure.that(rows).isLt(1, "00000005");
            if (entity.getFee().doubleValue() > 0) {
                Bill feeBillBean = new Bill();
                feeBillBean.setOrderId(SerialNumberWorker.getInstance().nextId());
                feeBillBean.setId(UF.getRandomUUID());
                feeBillBean.setMemberId(entity.getMemberId());
                feeBillBean.setAmount(entity.getFee());
                feeBillBean.setActualAmount(entity.getFee());
                feeBillBean.setFee(BigDecimal.ZERO);
                feeBillBean.setType(BillType.OUTLAY.getValue());
                feeBillBean.setTradeType(TradeType.WITHDRAW_FEE.getValue());
                rows = billMapper.insert(feeBillBean);
                Ensure.that(rows).isLt(1, "00000005");
            }

            // 触发短信
            Msg msg = new Msg();
            msg.setMemberId(entity.getMemberId());
            msg.setType(CommonConstants.MsgType.WITHDRAW.getIndex());
            Map<String, String> paramMap = new HashMap<>();
            paramMap.put("amount", BigDecimalUtil.to2Point(entity.getAmount()).toString());
            msg.setParamMap(paramMap);

            amqpTemplate.convertAndSend(QUEUE_MSG_SEND, msg);


            /**
             * 微信服务号消息推送  提现申请
             */
            WxMessageParamBean wxMessageParamBean = new WxMessageParamBean();
            wxMessageParamBean.setMemberId(entity.getMemberId());
            //消息推送类型
            wxMessageParamBean.setType(WxTemplateEnum.EXTRACT_FAILED.getType());
            WxTemplateEnum wxTemplateEnum = WxTemplateEnum.getWxTemplateByCode(WxTemplateEnum.EXTRACT_FAILED.getType());
            WxNotifyData wxNotifyData = new WxNotifyData();
            WithdrawAuditBean withdrawAuditBean = findByOrderId(entity.getOrderId());
            Map<String, WxNotifyData.TemplateDataAttr> wxParamMap = new HashMap();
            WxNotifyData.TemplateDataAttr first = new WxNotifyData.TemplateDataAttr();
            first.setDataValue(wxTemplateEnum.getFirstData());
            wxParamMap.put("first", first);

            WxNotifyData.TemplateDataAttr keyword1 = new WxNotifyData.TemplateDataAttr();
            keyword1.setDataValue(BigDecimalUtil.to2Point(entity.getAmount()).toString());
            wxParamMap.put("money", keyword1);

            WxNotifyData.TemplateDataAttr keyword2 = new WxNotifyData.TemplateDataAttr();
            keyword2.setDataValue(withdrawAuditBean.getAddTimeString());
            wxParamMap.put("timet", keyword2);

            WxNotifyData.TemplateDataAttr remark = new WxNotifyData.TemplateDataAttr();
            remark.setDataValue(wxTemplateEnum.getRemark());
            wxParamMap.put("remark", remark);

            wxNotifyData.setData(wxParamMap);
            wxMessageParamBean.setTemplateData(wxNotifyData);
            amqpTemplate.convertAndSend(QUEUE_MSG_WX_SEND, wxMessageParamBean);
            return 0;
        } catch (Exception e) {
            error("申请提现失败", e);
            throw e;
        } finally {
            redisGlobalLock.unlock(key);
        }
    }

    @Override
    @RemoveCache(cleanSearch = true, cleanObjectByKeyPosition = 0)
    public int delete(String id) {
        if (StringUtils.isBlank(id)) {
            return 0;
        }

        return withdrawMapper.delete(id);
    }

    @Override
    @RemoveCache(cleanSearch = true, cleanObjectByKeyPosition = 0)
    public int deleteByIds(String[] id) {
        if (id == null || id.length <= 0) {
            return 0;
        }

        return withdrawMapper.deleteByIds(id);
    }

    @Override
    @RemoveCache(cleanSearch = true, cleanObjectByKeyPosition = 0)
    public int removeByIds(String[] id) {
        if (id == null || id.length <= 0) {
            return 0;
        }

        return withdrawMapper.updateByPrimaryKeySelective(
                getParams()
                        .put("id", id)
                        .put("deleted", DeleteStatus.YES)
                        .toMap()
        );
    }

    @Override
    @SaveCache(cacheType = OBJECT)
    public WithdrawAuditBean findById(String id) {
        if (StringUtils.isBlank(id)) {
            return null;
        }

        Withdraw entity = withdrawMapper.findById(id);
        if (null == entity) {
            return null;
        }

        WithdrawAuditBean entityBean = dozerBeanMapper.map(entity, WithdrawAuditBean.class);
        entityBean.setAuditTimeOneString(UF.getFormatDateTime(entity.getAuditTimeOne()));
        entityBean.setAuditTimeTwoString(UF.getFormatDateTime(entity.getAuditTimeTwo()));
        entityBean.setAddTimeString(UF.getFormatDateTime(entity.getAddTime()));
        entityBean.setModifyTimeString(UF.getFormatDateTime(entity.getModifyTime()));
        return entityBean;
    }

    @Override
    public WithdrawAuditBean findByOrderId(String orderId) {
        if (StringUtils.isBlank(orderId)) {
            return null;
        }

        List<WithdrawAuditBean> list = queryDetail(null, null, null, orderId, null, null, null, null, null, null,
                null, null, null, null, null, null, null, null, null, null);
        if (null != list && list.size() > 0) {
            return list.get(0);
        }
        return null;
    }

    @Override
    @SaveCache(cacheType = SEARCH)
    public WithdrawAuditBean findDetailById(String id) {
        if (StringUtils.isBlank(id)) {
            return null;
        }

        List<WithdrawAuditBean> list = queryDetail(null, null, id, null, null, null, null, null, null, null,
                null, null, null, null, null, null, null, null, null, null);
        if (null != list && list.size() > 0) {
            return list.get(0);
        }
        return null;
    }

    @Override
    @SaveCache(cacheType = SEARCH)
    public DataOtherTable<WithdrawAuditBean> queryDetail(String order, String sort, int pageNum, int pageSize,
                                                         Integer type, Integer status, Integer auditStatus, BigDecimal amountMin, BigDecimal amountMax,
                                                         LocalDateTime addTimeMin, LocalDateTime addTimeMax, LocalDateTime modifyTimeMin, LocalDateTime modifyTimeMax,
                                                         String memberId, String memberName, String memberMobile, String keyword, List<Integer> auditStatusList, String channelId) {
        Page<WithdrawAuditBean> page = PageHelper.startPage(pageNum, pageSize);
        List<WithdrawAuditBean> list = queryDetail(order, sort, null, null, null, type,
                status, auditStatus, amountMin, amountMax,
                addTimeMin, addTimeMax, modifyTimeMin, modifyTimeMax,
                memberId, memberName, memberMobile, keyword, auditStatusList, channelId);
        Map params = new HashMap();
        params.put("status", status);
        params.put("amountMin", amountMin);
        params.put("amountMax", amountMax);
        params.put("addTimeMin", addTimeMin);
        params.put("addTimeMax", addTimeMax);
        params.put("memberName", UF.escapeSql(memberName));
        params.put("memberMobile", UF.escapeSql(memberMobile));
        params.put("auditStatusList", auditStatusList);
        Map resultMap = withdrawMapper.countQueryDetail(params);
        resultMap.put("status", status);
        return new DataOtherTable<>(page.getPageNum(), page.getPageSize(), page.getTotal(), list, resultMap);
    }

    @Override
    public int updateStatus(String orderId, int status, String description) {
        WithdrawAuditBean withdrawAuditBean = findByOrderId(orderId);
        String[] id = {withdrawAuditBean.getId()};

        return updateStatus(id, status, description);
    }

    @Override
    @RemoveCache(cleanSearch = true, cleanObjectByKeyPosition = 0)
    public int updateStatus(String[] id, int status, String description) {
        if (id == null || id.length <= 0) {
            return 0;
        }

        return withdrawMapper.updateByPrimaryKeySelective(
                getParams()
                        .put("id", id)
                        .put("status", status)
                        .put("description", description)
                        .toMap()
        );
    }

    @Override
    @RemoveCache(cleanSearch = true, cleanObjectByKeyPosition = 0)
    @Transactional(rollbackFor = Exception.class)
    public int audit(String[] id, int auditLevel, int auditStatus, String description, String userId, String userName) {
        if (id == null || id.length <= 0) {
            return 0;
        }
        // 审核意见（1：通过 2：拒绝）
        if (auditLevel == 1) {
            if (auditStatus == 1) {
                auditStatus = WithdrawAuditStatus.SUCCESS_ONE;
            } else {
                auditStatus = WithdrawAuditStatus.FAIL_ONE;
            }
            int rows = withdrawMapper.updateByPrimaryKeySelective(
                    getParams()
                            .put("id", id)
                            .put("auditStatus", auditStatus)
                            .put("auditTimeOne", UF.getDateTime())
                            .put("auditUserIdOne", userId)
                            .put("auditUserNameOne", userName)
                            .put("auditDescriptionOne", description)
                            .toMap()
            );
            Ensure.that(rows).isLt(id.length, "17000101");
            if (auditStatus == WithdrawAuditStatus.FAIL_ONE) {
                for (String _id : id) {
                    WithdrawAuditBean withdrawAuditBean = findById(_id);
                    memberAccountService.withdrawFail(withdrawAuditBean.getMemberId(), withdrawAuditBean.getActualAmount(), withdrawAuditBean.getActualAmount());
                    rows = billMapper.updateTradeTypeByOrderId(withdrawAuditBean.getOrderId(), TradeType.ACCOUNT_WITHDRWAL_RETURN.getValue(), BillType.INCOME.getValue());
                    Ensure.that(rows).isLt(1, "00000005");
                }
            }
            return rows;
        } else if (auditLevel == 2) {
            if (auditStatus == 1) {
                auditStatus = WithdrawAuditStatus.SUCCESS_TWO;
            } else {
                auditStatus = WithdrawAuditStatus.FAIL_TWO;
            }
            int rows = withdrawMapper.updateByPrimaryKeySelective(
                    getParams()
                            .put("id", id)
                            .put("auditStatus", auditStatus)
                            .put("auditTimeTwo", UF.getDateTime())
                            .put("auditUserIdTwo", userId)
                            .put("auditUserNameTwo", userName)
                            .put("auditDescriptionTwo", description)
                            .toMap()
            );
            Ensure.that(rows).isLt(id.length, "17000101");
            // 向接口发起提现

            for (String _id : id) {
                WithdrawAuditBean withdrawAuditBean = findById(_id);
                //当用户提现金额减去手续费后可到手金额为0时
                if (BigDecimalUtil.isZeroOrNull(withdrawAuditBean.getActualAmount())) {
                    tradeService.withdrawZeroMoney(withdrawAuditBean.getMemberId(), withdrawAuditBean.getOrderId(), withdrawAuditBean.getAmount());
                } else {
                    WithdrawMQ withdrawMQ = new WithdrawMQ();
                    withdrawMQ.setMemberId(withdrawAuditBean.getMemberId());
                    withdrawMQ.setOrderId(withdrawAuditBean.getOrderId());
                    withdrawMQ.setBankCardId(withdrawAuditBean.getBankCardId());
                    withdrawMQ.setAmount(withdrawAuditBean.getActualAmount());

                    info("向接口发起提现 = " + toJsonText(withdrawMQ));
                    amqpTemplate.convertAndSend(QUEUE_PAY_WITHDRAW, withdrawMQ);
                }
            }
        }
        return 0;
    }

    /**
     * 统计本月提醒数量
     *
     * @param memberId 会员ID
     * @return 数量
     */
    private long queryCountByThisMonth(String memberId) {
        LocalDateTime addTimeMin = UF.getDate(UF.getFormatDate("yyyy-MM-01", UF.getDateTime()));
        LocalDateTime addTimeMax = addTimeMin.plusMonths(1);

        // 审核状态  审核状态  1:未审核 2:一级审核成功 3一级审核失败 4:二级审核成功 5:二级审核失败
        List<Integer> auditStatusList = Arrays.asList(1, 2, 4);

        DataTable<WithdrawAuditBean> dataTable = queryDetail(null, null, 1, 1,
                null, null, null, null, null,
                addTimeMin, addTimeMax, null, null,
                memberId, null, null, null, auditStatusList, null);
        if (null == dataTable || null == dataTable.getDataList() || dataTable.getDataList().isEmpty()) {
            return 0;
        }
        return dataTable.getPage().getTotal();
    }

    /**
     * 获取数据列表
     *
     * @param order           排序字段
     * @param sort            排序方式 desc或asc
     * @param id              ID
     * @param orderId         订单号
     * @param thirdNumber     第三方流水号
     * @param type            提现类型  0:全部 1: T+0到账 2: T+1到账
     * @param status          提现状态  0:全部 1:待提现 2:处理中 3:成功 4:失败
     * @param auditStatus     审核状态  0:全部 1:未审核 2:一级审核成功 3一级审核失败 3:二级审核成功 4:二级审核失败
     * @param amountMin       最小提现金额
     * @param amountMax       最大提现金额
     * @param addTimeMin      最小操作时间
     * @param addTimeMax      最大操作时间
     * @param modifyTimeMin   最小反馈时间
     * @param modifyTimeMax   最大反馈时间
     * @param memberId        会员ID
     * @param memberName      会员名称
     * @param memberMobile    会员手机
     * @param keyword         关键字
     * @param auditStatusList 审核状态列表
     * @return 列表
     */
    private List<WithdrawAuditBean> queryDetail(String order, String sort, String id, String orderId, String thirdNumber, Integer type,
                                                Integer status, Integer auditStatus, BigDecimal amountMin, BigDecimal amountMax,
                                                LocalDateTime addTimeMin, LocalDateTime addTimeMax, LocalDateTime modifyTimeMin, LocalDateTime modifyTimeMax,
                                                String memberId, String memberName, String memberMobile, String keyword, List<Integer> auditStatusList, String channelId) {
        if (null != addTimeMax) {
            // 加一天减一秒
            addTimeMax = addTimeMax.plusDays(1).minusSeconds(1);
        }
        if (null != modifyTimeMax) {
            // 加一天减一秒
            modifyTimeMax = modifyTimeMax.plusDays(1).minusSeconds(1);
        }
        List<WithdrawAuditBean> dataList = new ArrayList<>();
        List<WithdrawDetail> list = withdrawMapper.queryDetail(
                getParams(keyword, order, sort)
                        .put("id", id)
                        .put("orderId", orderId)
                        .put("thirdNumber", thirdNumber)
                        .put("status", status)
                        .put("auditStatus", auditStatus)
                        .put("amountMin", amountMin)
                        .put("amountMax", amountMax)
                        .put("addTimeMin", addTimeMin)
                        .put("addTimeMax", addTimeMax)
                        .put("modifyTimeMin", modifyTimeMin)
                        .put("modifyTimeMax", modifyTimeMax)
                        .put("memberId", memberId)
                        .put("channelId", channelId)
                        .put("memberName", UF.escapeSql(memberName))
                        .put("memberMobile", UF.escapeSql(memberMobile))
                        .put("auditStatusList", auditStatusList)
                        .toMap());
        for (WithdrawDetail o : list) {
            WithdrawAuditBean objBean = dozerBeanMapper.map(o, WithdrawAuditBean.class);
            objBean.setAuditTimeOneString(UF.getFormatDateTime(o.getAuditTimeOne()));
            objBean.setAuditTimeTwoString(UF.getFormatDateTime(o.getAuditTimeTwo()));
            objBean.setAddTimeString(UF.getFormatDateTime(o.getAddTime()));
            objBean.setModifyTimeString(UF.getFormatDateTime(o.getModifyTime()));
            dataList.add(objBean);
        }
        return dataList;
    }


    @Override
    public JSONObject queryWithdrawInfo(String memberId, BigDecimal amount) {
        SerializeObject rateBean = rateSettingsService.get(RateKeyEnum.WITHDRAW.getKey());
        BigDecimal fee = BigDecimal.ZERO;
        Map<String, Object> relustMap = new HashMap<>();
        if (rateBean != null && rateBean.getData() != null) {
            JSONObject json = JSON.parseObject(JSONObject.toJSONString(rateBean.getData()));
            int dayNum = withdrawMapper.getWithdrawNumForThisDay(memberId);
            int monthNum = withdrawMapper.getWithdrawNumForThisMonth(memberId);

            int isFee = json.getIntValue("isFee");
            if (isFee == 1) {
                int feePeriod = json.getInteger("feePeriod");
                if (feePeriod == 1) {
                    json.put("withdrawNum", monthNum);
                    monthNum++;
                } else {
                    json.put("withdrawNum", dayNum);
                    dayNum++;
                }
                //amount 可能为空
                if (amount == null)
                    amount = BigDecimal.ZERO;

                fee = fundRateConfig.getFee(json, amount.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : amount, dayNum, monthNum);
                json.put("withdrawFee", fee);
                return json;
            }
        }
        return null;
    }

    public static void main(String[] args) {
        LocalDate localDate = LocalDate.now();
        LocalDate firstDayOfThisMonth = localDate.with(TemporalAdjusters.firstDayOfMonth()); // 2017-03-01
        System.out.println(firstDayOfThisMonth);
        BigDecimal str1 = new BigDecimal(5);
        BigDecimal str2 = new BigDecimal(4);
        System.out.println(str1.compareTo(str2));
    }
}

